home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / llist10.zip / LLIST.PAS < prev    next >
Pascal/Delphi Source File  |  1990-01-14  |  6KB  |  283 lines

  1. UNIT llist;
  2.  
  3. {Version 1.0, distributed as LLIST10.ZIP}
  4.  
  5. {This unit contains objects for doubly-linked lists.  See also DEMO.PAS
  6. and TEST.PAS in this archive.  For Turbo Pascal 5.5.
  7.  
  8. Please distribute this unit with its demo and test programs.  Also, 
  9. please retain in this unit credit to its original author and any 
  10. subsequent authors.
  11.  
  12. Donated to the public domain by Wayne E. Conrad, January, 1990.  If you
  13. have any problems or suggestions, please contact me at my BBS:
  14.  
  15.     Pascalaholics Anonymous
  16.     (602) 484-9356
  17.     2400 bps
  18.     The home of WBBS
  19.     Lots of source code
  20. }
  21.  
  22.  
  23. INTERFACE
  24.  
  25.  
  26. {This abstract type is for each node in a list.  It contains the data and
  27. methods needed to manage a node on the list, but it does not contain any
  28. useful data.  A descendant object should be created which contains the
  29. data you want in each node, as well as any methods to operate upon that
  30. data.}
  31.  
  32. TYPE
  33.   linked_list_ptr = ^linked_list_node;
  34.   linked_list_node =
  35.     OBJECT
  36.     prev: linked_list_ptr;
  37.     next: linked_list_ptr;
  38.     CONSTRUCTOR init;
  39.     DESTRUCTOR done;
  40.     PROCEDURE remove;
  41.     FUNCTION get_prev: linked_list_ptr;
  42.     FUNCTION get_next: linked_list_ptr;
  43.     PROCEDURE add_after (VAR node: linked_list_node);
  44.     PROCEDURE add_before (VAR node: linked_list_node);
  45.     END;
  46.  
  47.  
  48. {There must be one of these objects for each linked list.}
  49.  
  50. TYPE
  51.   linked_list_anchor =
  52.     OBJECT
  53.     first: linked_list_node;
  54.     last : linked_list_node;
  55.     CONSTRUCTOR init;
  56.     DESTRUCTOR done;
  57.     PROCEDURE remove_all_nodes;
  58.     PROCEDURE destruct_all_nodes;
  59.     PROCEDURE dispose_all_nodes;
  60.     FUNCTION get_first: linked_list_ptr;
  61.     FUNCTION get_last: linked_list_ptr;
  62.     FUNCTION empty: Boolean;
  63.     PROCEDURE add_to_head (VAR node: linked_list_node);
  64.     PROCEDURE add_to_tail (VAR node: linked_list_node);
  65.     END;
  66.  
  67.  
  68. IMPLEMENTATION
  69.  
  70.  
  71. {----- Methods for linked_list_anchor -----}
  72.  
  73. {Initialize the anchor to an empty list.  This method must be called
  74. before the anchor is used.}
  75.  
  76. CONSTRUCTOR linked_list_anchor.init;
  77. BEGIN
  78.   first.init;
  79.   last.init;
  80.   first.next := @last;
  81.   last.prev := @first
  82. END;
  83.  
  84.  
  85. {All nodes on the list are removed from the list.}
  86.  
  87. PROCEDURE linked_list_anchor.remove_all_nodes;
  88. VAR
  89.   p   : linked_list_ptr;
  90.   next: linked_list_ptr;
  91. BEGIN
  92.   p := get_first;
  93.   WHILE (p <> NIL) DO
  94.     BEGIN
  95.     next := p^.get_next;
  96.     p^.remove;
  97.     p := next
  98.     END
  99. END;
  100.  
  101.  
  102. {All nodes on the list are destructed.  All nodes will be removed from
  103. the list, in addition to whatever else the destructor cares to do.}
  104.  
  105. PROCEDURE linked_list_anchor.destruct_all_nodes;
  106. VAR
  107.   p   : linked_list_ptr;
  108.   next: linked_list_ptr;
  109. BEGIN
  110.   p := get_first;
  111.   WHILE (p <> NIL) DO
  112.     BEGIN
  113.     next := p^.get_next;
  114.     p^.done;
  115.     p := next
  116.     END
  117. END;
  118.  
  119.  
  120. {All nodes on the list are Disposed.  All nodes will be destructed,
  121. removing them from the list, and their memory returned to the heap.}
  122.  
  123. PROCEDURE linked_list_anchor.dispose_all_nodes;
  124. VAR
  125.   p   : linked_list_ptr;
  126.   next: linked_list_ptr;
  127. BEGIN
  128.   p := get_first;
  129.   WHILE (p <> NIL) DO
  130.     BEGIN
  131.     next := p^.get_next;
  132.     Dispose (p, done);
  133.     p := next
  134.     END
  135. END;
  136.  
  137.  
  138. {Destruct the anchor.  All nodes on the list are removed from the list.
  139. The nodes themselves are not destructed or disposed!  If you want to do
  140. THAT, invoke the "destruct_all_nodes" or "dispose_all_nodes" methods.}
  141.  
  142. DESTRUCTOR linked_list_anchor.done;
  143. VAR
  144.   p   : linked_list_ptr;
  145.   next: linked_list_ptr;
  146. BEGIN
  147.   remove_all_nodes
  148. END;
  149.  
  150.  
  151. {Returns a pointer to the first node in the list, or NIL if the list is
  152. empty.}
  153.  
  154. FUNCTION linked_list_anchor.get_first: linked_list_ptr;
  155. BEGIN
  156.   IF empty THEN
  157.     get_first := NIL
  158.   ELSE
  159.     get_first := first.next
  160. END;
  161.  
  162.  
  163. {Returns a pointer to the last node in the list, or NIL if the list is
  164. empty.}
  165.  
  166. FUNCTION linked_list_anchor.get_last: linked_list_ptr;
  167. BEGIN
  168.   IF empty THEN
  169.     get_last := NIL
  170.   ELSE
  171.     get_last := last.prev
  172. END;
  173.  
  174.  
  175. {Returns True if the list is empty.}
  176.  
  177. FUNCTION linked_list_anchor.empty: Boolean;
  178. BEGIN
  179.   empty := first.next = @last
  180. END;
  181.  
  182.  
  183. {Add the node to the head of this list.  If the node is already on a
  184. list, it is removed from that list first.}
  185.  
  186. PROCEDURE linked_list_anchor.add_to_head (VAR node: linked_list_node);
  187. BEGIN
  188.   node.add_after (first)
  189. END;
  190.  
  191.  
  192. {Add the node to the tail of this list.  If the node is already on a
  193. list, it is removed from that list first.}
  194.  
  195. PROCEDURE linked_list_anchor.add_to_tail (VAR node: linked_list_node);
  196. BEGIN
  197.   node.add_before (last)
  198. END;
  199.  
  200.  
  201. {----- Methods for linked_list_node -----}
  202.  
  203.  
  204. {Construct the node.  Must be invoked before the node is used.}
  205.  
  206. CONSTRUCTOR linked_list_node.init;
  207. BEGIN
  208.   prev := NIL;
  209.   next := NIL
  210. END;
  211.  
  212.  
  213. {Destruct the node.  If it's on a list, remove it.}
  214.  
  215. DESTRUCTOR linked_list_node.done;
  216. BEGIN
  217.   remove
  218. END;
  219.  
  220.  
  221. {If the node is on a list, remove it.}
  222.  
  223. PROCEDURE linked_list_node.remove;
  224. BEGIN
  225.   IF prev <> NIL THEN
  226.     prev^.next := next;
  227.   IF next <> NIL THEN
  228.     next^.prev := prev;
  229.   prev := NIL;
  230.   next := NIL
  231. END;
  232.  
  233. {Get the pointer to the previous node, or NIL if there is no previous
  234. node.}
  235.  
  236. FUNCTION linked_list_node.get_prev: linked_list_ptr;
  237. BEGIN
  238.   IF prev^.prev = NIL THEN
  239.     get_prev := NIL
  240.   ELSE
  241.    get_prev := prev
  242. END;
  243.  
  244.  
  245. {Get the pointer to the next node, or NIL if there is no next node.}
  246.  
  247. FUNCTION linked_list_node.get_next: linked_list_ptr;
  248. BEGIN
  249.   IF next^.next = NIL THEN
  250.     get_next := NIL
  251.   ELSE
  252.     get_next := next
  253. END;
  254.  
  255.  
  256. {If this node is in a list, remove it.  Then insert this node into
  257. whatever list p is in, putting it after p.}
  258.  
  259. PROCEDURE linked_list_node.add_after (VAR node: linked_list_node);
  260. BEGIN
  261.   remove;
  262.   next := node.next;
  263.   prev := @node;
  264.   next^.prev := @Self;
  265.   prev^.next := @Self
  266. END;
  267.  
  268.  
  269. {If this node is in a list, remove it.  Then insert this node into
  270. whatever list p is in, putting it before p.}
  271.  
  272. PROCEDURE linked_list_node.add_before (VAR node: linked_list_node);
  273. BEGIN
  274.   remove;
  275.   prev := node.prev;
  276.   next := @node;
  277.   prev^.next := @Self;
  278.   next^.prev := @Self
  279. END;
  280.  
  281.  
  282. END.
  283.